/***************************************************************************
 *   Copyright (C) 2007 by Ziman & Xloverin                                *
 *   ziman@centrum.sk, xloverin@gmail.com                                  *
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 *   This program is distributed in the hope that it will be useful,       *
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
 *   GNU General Public License for more details.                          *
 *                                                                         *
 *   You should have received a copy of the GNU General Public License     *
 *   along with this program; if not, write to the                         *
 *   Free Software Foundation, Inc.,                                       *
 *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
 ***************************************************************************/
#ifndef CORE_H
#define CORE_H

#include <QList>
#include <QObject>
#include <QSet>
#include <QtSql/QSqlDatabase>
#include <QDateTime>
#include "connection.h"
#include "mainform.h"
#include "config.h"
#include "query.h"
#include "preferences.h"
#include "prefsqueries.h"
#include "log.h"
#include "line.h"
#include "tagcache.h"
#include "nicklist.h"

/**
 * Jadro klienta.
 * @author Ziman & Xloverin <ziman@centrum.sk, xloverin@gmail.com>
 */
class Core : public QObject {
	
public:
		
	/// Rezim citania.
	enum ReadMode {
		/// Po znakoch.
		rmChar,
  		/// Po riadkoch.
  		rmLine
	};

private:

	/// Prikazy talkra.
	enum Command {
		cNone,
		cStatus,
  		cMacro
	};

	typedef QSet<Query *> Queries;
	typedef QSet<QString> MacroNames;

	/// Zoznam vsetkych queries.
	Queries queries;
	
	MacroNames m_macroNames;

	MainForm *mainForm;
	Query *m_mainQuery;
	Log *m_log;
	Connection *connection;
	Config *config;

	bool m_afk;
	
	/// Zoznam nickov na talkri.
	NickList *m_nickList;
	
	/// Tag cache.
	TagCache *m_tagCache;
	
	/// Rezim citania.
	ReadMode m_readMode;

	Preferences::Prefs m_preferences;

	/// Kvera, ktora ziskala exkluzivitu na vstup.
	Query *m_inputCapture;

	/// Pripojenie k databaze.
	QSqlDatabase db;

	/// Vravi, ci je user lognuty.
	bool m_loggedIn;

	/// Nick usera.
	QString m_nick;

	/// Cas, kedy bol user lognuty. Ak nebol, nedefinovane.
	QDateTime m_loginTime;

	/// Cas, kedy user naposledy poslal talkru nejaky riadok. Ak neposlal, nedefinovane.
	QDateTime m_lastActTime;

	/**
	 * Prikaz, na ktoreho vystup sa caka. Je to kvoli bezpecnosti, aby sa
	 * neparsoval podstrceny echovany text, ale iba ozaj vyziadane vystupy.
	 */
	Command curCmd;

	/// Otvori defaultne queries podla udajov v databaze.
	void openDefaultQueries();

	/// Loadne defaultne queries z databazy.
	PrefsQueries::QueryList loadDefaultQueries();

	/// Ulozi defaultne queries do databazy.
	void saveDefaultQueries(PrefsQueries::QueryList queryList);

	/**
	 * Spracuje riadok na ine ucely, nez je vypisovanie do okna. Pouziva sa
	 * napriklad pri logine, kedy sa spusti .status, ale vystup prikazu sa
	 * uzivatelovi nevypise; namiesto toho sa odtial vycucnu udaje.
	 * @param rawLine Prijaty riadok.
	 * @return True, ak sa ma riadok vypisat (niekam, do query alebo do
	 * 	hlavneho okna).
	 * @warning Este to nie je kompletne implementovane!
	 * @todo Domysliet system.
	 */
	bool filterLine(const Line &line);

	/// Prejde do alebo odide z AFK.
	void setAfk(bool afk);
	
	/// Vola sa pri parsnuti lajny v znakovom mode.
	void onLineInCharMode(const QByteArray &data);

	Q_OBJECT

private slots:
	virtual void on_connection_lineDataReady(const QByteArray &data);
	virtual void on_connection_connected();
	virtual void on_connection_disconnected();
	virtual void on_connection_charDataReady(const QByteArray &data);

public slots:
	void onUserActivity();

public:
	
	void connectTalker();
	void disconnectTalker();
	bool connected();

	QSqlDatabase *getDb();
	Connection *getConnection();
	Config *getConfig();
	Query *inputCapture();
	void setInputCapture(Query *inputCapture);
	void setHilightLevel(Query *query, Query::HilightLevel level);

	/// Nastavi preferences a aplikuje ich.
	void setPreferences(Preferences::Prefs prefs);

	/// Vrati nastavene preferences.
	const Preferences::Prefs &preferences();

	/// Ulozi nastavene preferences do databazy.
	void savePreferences(Preferences::Prefs prefs);

	/// Loadne preferences z databazy.
	Preferences::Prefs loadPreferences();

	/// Vrati, ci sme v AFK.
	bool afk();
	
	/// Vrati tag cache.
	TagCache &tagCache();
	
	/// Rezim citania.
	ReadMode readMode() const;
	
	void setReadMode(ReadMode mode);
	
	/// Zobrazi gossipovu query.
	void displayGossipQuery();

	Log *log();

	bool loggedIn();
	QString nick();
	QDateTime loginTime();
	QDateTime lastActTime();

	Query *addQuery(Query::Prefs prefs, Terminal *terminal = 0);
	void deleteQuery(Query *query);

	/// Ulozi aktualne otvorene queries ako defaultne.
	void saveCurrentQueriesAsDefault();
	
	/// Vrati zoznam nickov na talkri.
	NickList &nickList();
	
	void refreshMacros();
	bool macroDefined(QString name);

    Core(MainForm *mainForm);
	virtual ~Core();

signals:
	void login(QString nick);

};

#endif
